package org.dx.oho.book.one.interceptor;

import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * create by duanx 2021/5/24

 *@description： todo
 *@classname: InterceptorJdkProxy
 *@author: duanx
 *@date: 2021/5/24 23:45
 **/
public class InterceptorJdkProxy implements InvocationHandler {

    /**
     * 日志
     */
    private Logger logger = LoggerFactory.getLogger(InterceptorJdkProxy.class);

    /**
     * 代理目标
     */
    private Object target;

    /**
     * 拦截器名称
     */
    private String interceptorClass = null;

    /**
     * 全参构造器
     * @param target
     * @param interceptorClass
     */
    private InterceptorJdkProxy(Object target,String interceptorClass){
        this.target=target;
        this.interceptorClass=interceptorClass;
    }

    /**
     * 绑定代理对象和代理目标
     * @param target
     * @param interceptorClass
     * @return
     */
    @NotNull
    public static Object bind(@NotNull Object target, String interceptorClass){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new InterceptorJdkProxy(target,interceptorClass));
    }


    /**
     *
     * @param proxy 代理
     * @param method 方法
     * @param args 参数
     * @return 代理结果
     * @throws Throwable 异常
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //没有设置拦截器 直接反射原有方法
        if (interceptorClass==null){
            return method.invoke(target,args);
        }
        //设置反射器了
        Object result = null;
        //通过反射器生成拦截器
        Interceptor interceptor = (Interceptor) Class.forName(interceptorClass).newInstance();
        //调用前置方法 true直接执行代理方法 否则执行around方法
        if (interceptor.before(proxy,target,method,args)){
            result = method.invoke(target,args);
        }else {
            interceptor.around(proxy,target,method,args);
        }
        //执行后置方法
        interceptor.after(proxy,target,method,args);
        return result;
    }
}
